/********************************************************************************
* @file    os_api.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-08-27
* @brief   FreeRTOS Kernel V10.0.0
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>

#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "freertos_mpool.h"
#include "queue_os.h"
#include "semphr.h"
#include "task.h"
#include "timers.h"
/* Private Includes ----------------------------------------------------------*/
#include "cmsis_os.h"
#include "log.h"
#include "os_api.h"

/* Private Define ------------------------------------------------------------*/
#ifndef __ARM_ARCH_6M__
  #define __ARM_ARCH_6M__         0
#endif
#ifndef __ARM_ARCH_7M__
  #define __ARM_ARCH_7M__         0
#endif
#ifndef __ARM_ARCH_7EM__
  #define __ARM_ARCH_7EM__        0
#endif
#ifndef __ARM_ARCH_8M_MAIN__
  #define __ARM_ARCH_8M_MAIN__    0
#endif
#ifndef __ARM_ARCH_7A__
  #define __ARM_ARCH_7A__         0
#endif

#if   ((__ARM_ARCH_7M__      == 1U) || \
       (__ARM_ARCH_7EM__     == 1U) || \
       (__ARM_ARCH_8M_MAIN__ == 1U))
#define IS_IRQ_MASKED()           ((__get_PRIMASK() != 0U) || (__get_BASEPRI() != 0U))
#elif  (__ARM_ARCH_6M__      == 1U)
#define IS_IRQ_MASKED()           (__get_PRIMASK() != 0U)
#elif (__ARM_ARCH_7A__       == 1U)
/* CPSR mask bits */
#define CPSR_MASKBIT_I            0x80U

#define IS_IRQ_MASKED()           ((__get_CPSR() & CPSR_MASKBIT_I) != 0U)
#else
#define IS_IRQ_MASKED()           (__get_PRIMASK() != 0U)
#endif

#if    (__ARM_ARCH_7A__      == 1U)
/* CPSR mode bitmasks */
#define CPSR_MODE_USER            0x10U
#define CPSR_MODE_SYSTEM          0x1FU

#define IS_IRQ_MODE()             ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
#else
#define IS_IRQ_MODE()             (__get_IPSR() != 0U)
#endif

#define IS_IRQ()                  (IS_IRQ_MODE() || (IS_IRQ_MASKED() && (KernelState == osKernelRunning)))

/* Limits */
#define MAX_BITS_TASK_NOTIFY      31U
#define MAX_BITS_EVENT_GROUPS     24U

#define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY)  - 1U))
#define EVENT_FLAGS_INVALID_BITS  (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))

/* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */
#define KERNEL_VERSION            (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) | \
                                   ((uint32_t)tskKERNEL_VERSION_MINOR *    10000UL) | \
                                   ((uint32_t)tskKERNEL_VERSION_BUILD *        1UL))

#define KERNEL_ID                 ("FreeRTOS " tskKERNEL_VERSION_NUMBER)

/* Private Typedef -----------------------------------------------------------*/
#if configUSE_TRACE_FACILITY
/* Used with the uxTaskGetSystemState() function to return the state of each task in the system. */
typedef struct
{
    const char *pcTaskName;         /* 指向任务名称的指针 */
    uint16_t usStackHighWaterMark;  /* 自创建任务以来，为该任务保留的最小堆栈空间。 这个值越接近于零，任务就越接近于溢出它的堆栈 */
} task_stack_t;
task_stack_t os_task_stack[configThread_Quantity] = {0};
#endif

/* Timer callback information structure definition */
typedef struct {
  osTimerFunc_t func;
  void         *arg;
} TimerCallback_t;

/* Private Macro -------------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
/* Kernel initialization state */
static osKernelState_t KernelState = osKernelInactive;

/*
  Function macro used to retrieve semaphore count from ISR
*/
#ifndef uxSemaphoreGetCountFromISR
#define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) )
#endif

// 记录线程ID
static TaskHandle_t m_task_id[configThread_Quantity] = {0};
static uint8_t m_task_id_tick = 0;

/* Public Function Prototypes -----------------------------------------------*/
/*********************************OS_KERNEL***********************************/
os_status os_kernel_initialize(void)
{
    os_status stat;

    if (IS_IRQ())
    {
        stat = OS_ERROR_ISR;
    }
    else
    {
        if (KernelState == osKernelInactive)
        {
#if defined(USE_TRACE_EVENT_RECORDER)
            EvrFreeRTOSSetup(0U);
#endif
#if defined(USE_FreeRTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1)
            vPortDefineHeapRegions(configHEAP_5_REGIONS);
#endif
            KernelState = osKernelReady;
            stat = OS_OK;
        }
        else
        {
            stat = OS_ERROR_PARAMETER;
        }
    }

    return (stat);
}

os_status os_kernel_start(void)
{
    os_status stat;

    if (IS_IRQ())
    {
        stat = OS_ERROR_ISR;
    }
    else
    {
        if (KernelState == osKernelReady)
        {
            /* Change state to enable IRQ masking check */
            KernelState = osKernelRunning;
            /* Start the kernel scheduler */
            vTaskStartScheduler();
            stat = OS_OK;
        }
        else
        {
            stat = OS_ERROR_PARAMETER;
        }
    }
    return (stat);
}

os_status os_delay(uint32_t ms)
{
    if (IS_IRQ())
    {
        return OS_ERROR_ISR;
    }
    if (ms != 0)
    {
        vTaskDelay(ms);
    }
    return OS_OK;
}

os_status os_kernel_lock(void)
{
    os_status lock;

    if (IS_IRQ())
    {
        lock = OS_ERROR_ISR;
    }
    else
    {
        switch (xTaskGetSchedulerState())
        {
        case taskSCHEDULER_SUSPENDED:
            lock = (os_status)1;
            break;

        case taskSCHEDULER_RUNNING:
            vTaskSuspendAll();
            lock = OS_OK;
            break;

        case taskSCHEDULER_NOT_STARTED:
        default:
            lock = OS_ERROR_PARAMETER;
            break;
        }
    }
    return (lock);
}

os_status os_kernel_unlock(void)
{
    os_status lock;

    if (IS_IRQ())
    {
        lock = OS_ERROR_ISR;
    }
    else
    {
        switch (xTaskGetSchedulerState())
        {
        case taskSCHEDULER_SUSPENDED:
            lock = (os_status)1;
            if (xTaskResumeAll() != pdTRUE)
            {
                if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED)
                {
                    lock = OS_ERROR_PARAMETER;
                }
            }
            break;

        case taskSCHEDULER_RUNNING:
            lock = OS_OK;
            break;

        case taskSCHEDULER_NOT_STARTED:
        default:
            lock = OS_ERROR_PARAMETER;
            break;
        }
    }
    return (lock);
}

uint32_t os_get_tick(void)
{
    TickType_t ticks;

    if (IS_IRQ())
    {
        ticks = xTaskGetTickCountFromISR();
    }
    else
    {
        ticks = xTaskGetTickCount();
    }
    return (ticks);
}

/************************************OS_THREAD************************************/
os_thread_id os_thread_create(const os_thread_def_t *thread_def, void *arg)
{
    if (m_task_id_tick >= configThread_Quantity)
    {
        return NULL;
    }
    if (xTaskCreate((TaskFunction_t)thread_def->pthread, arg, thread_def->stacksize, NULL, thread_def->tpriority, m_task_id + m_task_id_tick))
    {
        m_task_id_tick++;
        return (os_thread_id)m_task_id[m_task_id_tick - 1];
    }
    return NULL;
}

/************************************OS_TIMER************************************/
static void TimerCallback(TimerHandle_t hTimer)
{
    TimerCallback_t *callb;

    callb = (TimerCallback_t *)pvTimerGetTimerID(hTimer);

    if (callb != NULL)
    {
        callb->func(callb->arg);
    }
}

os_timer_id os_timer_create(const os_timer_def_t *timer_def, os_timer_t type, void *arg)
{
    TimerHandle_t hTimer = NULL;
    TimerCallback_t *callb = NULL;

    if (!IS_IRQ() && (timer_def->ptimer != NULL))
    {
        /* Allocate memory to store callback function and argument */
        callb = pvPortMalloc (sizeof(TimerCallback_t));
        if (callb != NULL) 
        {
            callb->func = (osTimerFunc_t)timer_def->ptimer;
            callb->arg  = arg;

            hTimer = xTimerCreate(timer_def->timer, 1, type, callb, TimerCallback);
            if ((hTimer == NULL) && (callb != NULL))
            {
                vPortFree(callb);
            }
        }
    }
    return ((os_timer_id)hTimer);
}

os_status os_timer_start(os_timer_id timer_id, uint32_t millisec)
{
    TimerHandle_t hTimer = (TimerHandle_t)timer_id;
    os_status stat;

    if (IS_IRQ())
    {
        stat = OS_ERROR_ISR;
    }
    else if (hTimer == NULL)
    {
        stat = OS_ERROR_PARAMETER;
    }
    else
    {
        if (xTimerChangePeriod(hTimer, millisec, 0))
        {
            stat = OS_OK;
        }
        else
        {
            stat = OS_ERROR_RESOURCE;
        }
    }
    return (stat);
}

os_status os_timer_stop(os_timer_id timer_id)
{
    TimerHandle_t hTimer = (TimerHandle_t)timer_id;
    os_status stat;

    if (IS_IRQ())
    {
        stat = OS_ERROR_ISR;
    }
    else if (hTimer == NULL)
    {
        stat = OS_ERROR_PARAMETER;
    }
    else
    {
        if (xTimerIsTimerActive(hTimer) == (BaseType_t)false)
        {
            stat = OS_ERROR_RESOURCE;
        }
        else
        {
            if (xTimerStop(hTimer, 0))
            {
                stat = OS_OK;
            }
            else
            {
                stat = OS_ERROR_OS;
            }
        }
    }
    return (stat);
}

/************************************OS_MAIL************************************/
os_mail_qid os_mail_create(const os_mailq_def_t *queue_def, os_thread_id thread_id)
{
    return 0;
}

void *os_mail_alloc(os_mail_qid queue_id, uint32_t millisec)
{
    return NULL;
}

void *os_mail_clean_and_alloc(os_mail_qid queue_id, uint32_t millisec)
{
    return NULL;
}

os_status os_mail_put(os_mail_qid queue_id, void *mail)
{
    return OS_ERROR_OS;
}

os_event os_mail_get(os_mail_qid queue_id, uint32_t millisec, void *arg)
{
    os_event event_t;
    return event_t;
}

os_status os_mail_free(os_mail_qid queue_id, void *mail)
{
    return OS_ERROR_OS;
}

/************************************OS_POOL************************************/
/* Static memory pool functions */
static void  FreeBlock   (MemPool_t *mp, void *block);
static void *AllocBlock  (MemPool_t *mp);
static void *CreateBlock (MemPool_t *mp);
os_pool_id os_pool_create(const os_pool_def_t *pool_def)
{
    MemPool_t *mp = NULL;
    const char *name = pool_def->pool;
    uint32_t sz = MEMPOOL_ARR_SIZE (pool_def->pool_sz, pool_def->item_sz);
    if (IS_IRQ())
    {
        mp = NULL;
    }
    else if ((pool_def->pool_sz == 0U) || (pool_def->item_sz == 0U))
    {
        mp = NULL;
    }
    else
    {
        mp = pvPortMalloc(sizeof(MemPool_t));
        if (mp != NULL)
        {
            mp->sem = xSemaphoreCreateCounting(pool_def->pool_sz, pool_def->pool_sz);
            if (mp->sem != NULL) 
            {
                mp->mem_arr = pvPortMalloc (sz);
            }
        }
        if ((mp != NULL) && (mp->mem_arr != NULL))
        {
            /* Memory pool can be created */
            mp->head = NULL;
            mp->mem_sz = sz;
            mp->name = name;
            mp->bl_sz = pool_def->item_sz;
            mp->bl_cnt = pool_def->pool_sz;
            mp->n = 0U;

            /* Set heap allocated memory flags */
            mp->status = MPOOL_STATUS;
            /* Control block on heap */
            mp->status |= 1U;
            /* Memory array on heap */
            mp->status |= 2U;
        }
        else
        {
            /* Memory pool cannot be created, release allocated resources */
            if (mp != NULL)
            {
                /* Free control block memory */
                vPortFree(mp);
            }
            mp = NULL;
        }
    }
    return (os_pool_id)mp;
}

void *os_pool_alloc(os_pool_id pool_id)
{
    MemPool_t *mp;
    void *block;
    uint32_t isrm;

    if (pool_id == NULL)
    {
        /* Invalid input parameters */
        block = NULL;
    }
    else
    {
        block = NULL;
        mp = (MemPool_t *)pool_id;
        if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS)
        {
            if (IS_IRQ())
            {
                if (xSemaphoreTakeFromISR(mp->sem, NULL) == (BaseType_t)true)
                {
                    if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS)
                    {
                        isrm = taskENTER_CRITICAL_FROM_ISR();
                        /* Get a block from the free-list */
                        block = AllocBlock(mp);

                        if (block == NULL)
                        {
                            /* List of free blocks is empty, 'create' new block */
                            block = CreateBlock(mp);
                        }
                        taskEXIT_CRITICAL_FROM_ISR(isrm);
                    }
                }
            }
            else
            {
                if (xSemaphoreTake(mp->sem, (TickType_t)0) == (BaseType_t)true)
                {
                    if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS)
                    {
                        taskENTER_CRITICAL();
                        /* Get a block from the free-list */
                        block = AllocBlock(mp);
                        if (block == NULL)
                        {
                            /* List of free blocks is empty, 'create' new block */
                            block = CreateBlock(mp);
                        }
                        taskEXIT_CRITICAL();
                    }
                }
            }
        }
    }
    return (block);
}

void *os_pool_calloc(os_pool_id pool_id)
{
   return os_pool_alloc(pool_id);
}

os_status os_pool_free(os_pool_id pool_id, void *block)
{
    MemPool_t *mp;
    os_status stat;
    uint32_t isrm;
    BaseType_t yield;

    if ((pool_id == NULL) || (block == NULL))
    {
        /* Invalid input parameters */
        stat = OS_ERROR_PARAMETER;
    }
    else
    {
        mp = (MemPool_t *)pool_id;

        if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS)
        {
            /* Invalid object status */
            stat = OS_ERROR_RESOURCE;
        }
        else if ((block < (void *)&mp->mem_arr[0]) || (block > (void *)&mp->mem_arr[mp->mem_sz - 1]))
        {
            /* Block pointer outside of memory array area */
            stat = OS_ERROR_PARAMETER;
        }
        else
        {
            stat = OS_OK;
            if (IS_IRQ())
            {
                if (uxSemaphoreGetCountFromISR(mp->sem) == mp->bl_cnt)
                {
                    stat = OS_ERROR_RESOURCE;
                }
                else
                {
                    isrm = taskENTER_CRITICAL_FROM_ISR();
                    /* Add block to the list of free blocks */
                    FreeBlock(mp, block);
                    taskEXIT_CRITICAL_FROM_ISR(isrm);
                    yield = pdFALSE;
                    xSemaphoreGiveFromISR(mp->sem, &yield);
                    portYIELD_FROM_ISR(yield);
                }
            }
            else
            {
                if (uxSemaphoreGetCount(mp->sem) == mp->bl_cnt)
                {
                    stat = OS_ERROR_RESOURCE;
                }
                else
                {
                    taskENTER_CRITICAL();
                    /* Add block to the list of free blocks */
                    FreeBlock(mp, block);
                    taskEXIT_CRITICAL();
                    xSemaphoreGive(mp->sem);
                }
            }
        }
    }

    return (stat);
}

uint8_t os_pool_get_space(os_pool_id pool_id)
{
    MemPool_t *mp;
    uint32_t n;

    if (pool_id == NULL)
    {
        /* Invalid input parameters */
        n = 0U;
    }
    else
    {
        mp = (MemPool_t *)pool_id;

        if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS)
        {
            /* Invalid object status */
            n = 0U;
        }
        else
        {
            if (IS_IRQ())
            {
                n = uxSemaphoreGetCountFromISR(mp->sem);
            }
            else
            {
                n = uxSemaphoreGetCount(mp->sem);
            }
        }
    }

    /* Return number of memory blocks available */
    return (n);
}

/*
  Create new block given according to the current block index.
*/
static void *CreateBlock(MemPool_t *mp)
{
    MemPoolBlock_t *p = NULL;
    if (mp->n < mp->bl_cnt)
    {
        /* Unallocated blocks exist, set pointer to new block */
        p = (void *)(mp->mem_arr + (mp->bl_sz * mp->n));
        /* Increment block index */
        mp->n += 1U;
    }
    return (p);
}

/*
  Allocate a block by reading the list of free blocks.
*/
static void *AllocBlock(MemPool_t *mp)
{
    MemPoolBlock_t *p = NULL;
    if (mp->head != NULL)
    {
        /* List of free block exists, get head block */
        p = mp->head;
        /* Head block is now next on the list */
        mp->head = p->next;
    }
    return (p);
}

/*
  Free block by putting it to the list of free blocks.
*/
static void FreeBlock(MemPool_t *mp, void *block)
{
    MemPoolBlock_t *p = block;
    /* Store current head into block memory space */
    p->next = mp->head;
    /* Store current block as new head */
    mp->head = p;
}

/************************************OS_MSG_QUEUE************************************/
/**
 * @brief  [消息队列] 创建消息队列空间
 * @note   NULL
 * @param  queue_def : 消息队列信息(大小)
 * @param  thread_id : 线程ID（可以无视不填）
 * @retval None
 */
os_message_qid os_message_create(const os_messageq_def_t *queue_def, os_thread_id thread_id)
{
    QueueHandle_t hQueue = NULL;
    if (!IS_IRQ() && (queue_def->queue_sz > 0U)) 
    {
        hQueue = xQueueCreate(queue_def->queue_sz, 4);
        if (queue_def->attr.name);
#if (configQUEUE_REGISTRY_SIZE > 0)
        if (hQueue != NULL)
        {
            vQueueAddToRegistry(hQueue, queue_def->attr.name);
        }
#endif
    }
    return ((os_message_qid)hQueue);
}

/**
 * @brief  [消息队列] 发送一组消息队列数据
 * @note   NULL
 * @param  queue_id: 消息队列ID
 * @param  info    : 消息指针
 * @param  millisec: 超时时间 0xFFFFFFFF 无限等待
 * @retval None
 */
os_status os_message_put(os_message_qid queue_id, uint32_t info, uint32_t millisec)
{
    QueueHandle_t hQueue = (QueueHandle_t)queue_id;
    os_status stat;
    BaseType_t yield;
    stat = OS_OK;

    if (IS_IRQ())
    {
        if ((hQueue == NULL) || (info == NULL) || (millisec != 0U))
        {
            stat = OS_ERROR_PARAMETER;
        }
        else
        {
            yield = false;
            if (xQueueSendToBackFromISR(hQueue, (const void *)&info, &yield) != (BaseType_t)true)
            {
                stat = OS_ERROR_RESOURCE;
            }
            else
            {
                portYIELD_FROM_ISR(yield);
            }
        }
    }
    else
    {
        if ((hQueue == NULL) || (info == NULL))
        {
            stat = OS_ERROR_PARAMETER;
        }
        else
        {
            if (xQueueSendToBack(hQueue, (const void *)&info, (TickType_t)millisec) != (BaseType_t)true)
            {
                if (millisec != 0U)
                {
                    stat = OS_EVENT_TIMEOUT;
                }
                else
                {
                    stat = OS_ERROR_RESOURCE;
                }
            }
        }
    }
    //LOG_D("os_msg_put:0x%x|0x%x", queue_id, info);
    return stat;
}

/**
 * @brief  [消息队列] 得到一组消息队列数据
 * @note   NULL
 * @param  queue_id: 消息队列ID
 * @param  millisec: 等待时间 0xFFFFFFFF 无限等待
 * @retval None
 */
os_event os_message_get(os_message_qid queue_id, uint32_t millisec)
{
    QueueHandle_t hQueue = (QueueHandle_t)queue_id;
    BaseType_t yield;
    uint32_t *msg_ptr;
    os_event event;

    event.status = OS_OK;
    if (IS_IRQ())
    {
        if ((hQueue == NULL) || (millisec != 0U))
        {
            event.status = OS_ERROR_PARAMETER;
        }
        else
        {
            yield = false;
            if (xQueueReceiveFromISR(hQueue, &msg_ptr, &yield) != true)
            {
                event.status = OS_ERROR_RESOURCE;
            }
            else
            {
                event.status = OS_EVENT_MESSAGE;
                event.value.p = (void *)msg_ptr;
                portYIELD_FROM_ISR(yield);
            }
        }
    }
    else
    {
        if (hQueue == NULL)
        {
            event.status = OS_ERROR_PARAMETER;
        }
        else
        {
            if (xQueueReceive(hQueue, &msg_ptr, (TickType_t)millisec) != true)
            {
                if (millisec != 0U)
                {
                    event.status = OS_EVENT_TIMEOUT;
                }
                else
                {
                    event.status = OS_ERROR_RESOURCE;
                }
            }
            else
            {
                event.status = OS_EVENT_MESSAGE;
                event.value.p = (void *)msg_ptr;
                //LOG_D("os_msg_get:0x%x|0x%x", queue_id, msg_ptr);
            }
        }
    }

    return event;
}

/**
 * @brief  [消息队列] 得到当前剩余量
 * @note   NULL
 * @param  queue_id: 消息队列ID
 * @retval 返回当前剩余量
 */
uint8_t os_message_get_space(os_message_qid queue_id)
{
    StaticQueue_t *mq = (StaticQueue_t *)queue_id;
    uint32_t space;
    uint32_t isrm;

    if (mq == NULL)
    {
        space = 0U;
    }
    else if (IS_IRQ())
    {
        isrm = taskENTER_CRITICAL_FROM_ISR();

        /* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
        space = mq->uxDummy4[1] - mq->uxDummy4[0];

        taskEXIT_CRITICAL_FROM_ISR(isrm);
    }
    else
    {
        space = (uint32_t)uxQueueSpacesAvailable((QueueHandle_t)mq);
    }

    return (uint8_t)space;
}

/**
 * @brief  [消息队列] 得到当前使用量
 * @note   NULL
 * @param  queue_id: 消息队列ID
 * @retval 返回当前使用量
 */
uint8_t os_message_get_count(os_message_qid queue_id)
{
    QueueHandle_t hQueue = (QueueHandle_t)queue_id;
    UBaseType_t count;

    if (hQueue == NULL)
    {
        count = 0U;
    }
    else if (IS_IRQ())
    {
        count = uxQueueMessagesWaitingFromISR(hQueue);
    }
    else
    {
        count = uxQueueMessagesWaiting(hQueue);
    }
    return count;
}

/************************************OS_SIGNAL************************************/
int32_t isr_signal_set(os_thread_id thread_id, int32_t signals)
{
    return os_signal_set(thread_id, signals);
}

int32_t os_signal_set(os_thread_id thread_id, int32_t signals)
{
    TaskHandle_t hTask = (TaskHandle_t)thread_id;
    uint32_t rflags;
    BaseType_t yield;
    // LOG_D("os_signal_set:0x%x\r\n", (uint32_t)hTask);
    if ((hTask == NULL) || ((signals & THREAD_FLAGS_INVALID_BITS) != 0U))
    {
        rflags = (uint32_t)OS_ERROR_PARAMETER;
    }
    else
    {
        rflags = (uint32_t)OS_OK;
        if (IS_IRQ())
        {
            yield = false;
            (void)xTaskNotifyFromISR(hTask, signals, eSetBits, &yield);
            (void)xTaskNotifyAndQueryFromISR(hTask, 0, eNoAction, &rflags, NULL);

            portYIELD_FROM_ISR(yield);
        }
        else
        {
            (void)xTaskNotify(hTask, signals, eSetBits);
            (void)xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags);
        }
    }
    // LOG_D("os_signal_set_rflags:0x%x\r\n", (uint32_t)rflags);
    /* Return flags after setting */
    return (rflags);
}

int32_t os_signal_clear(os_thread_id thread_id, int32_t signals)
{
    TaskHandle_t hTask = (TaskHandle_t)thread_id;
    uint32_t rflags, cflags;
    
    if (IS_IRQ())
    {
        rflags = (uint32_t)OS_ERROR_ISR;
    }
    else if ((signals & THREAD_FLAGS_INVALID_BITS) != 0U)
    {
        rflags = (uint32_t)OS_ERROR_PARAMETER;
    }
    else
    {
        if (xTaskNotifyAndQuery(hTask, 0, eNoAction, &cflags) == (BaseType_t)true)
        {
            rflags = cflags;
            cflags &= ~signals;
            if (xTaskNotify(hTask, cflags, eSetValueWithOverwrite) != (BaseType_t)true)
            {
                rflags = (uint32_t)OS_ERROR_OS;
            }
        }
        else
        {
            rflags = (uint32_t)OS_ERROR_OS;
        }
    }
    /* Return flags before clearing */
    return (rflags);
}

// signals = 0,则等待任意信号.
os_event os_signal_wait(int32_t signals, uint32_t millisec)
{
    BaseType_t rval;
    os_event event_t;

    if (IS_IRQ())
    {
        event_t.status = OS_ERROR_ISR;
    }
    else if ((signals & THREAD_FLAGS_INVALID_BITS) != 0U)
    {
        event_t.status = OS_ERROR_PARAMETER;
    }
    else
    {
        rval = xTaskNotifyWait(signals, 0xFFFFFFFF, (uint32_t *)&(event_t.value.signals), millisec);
        if (rval == true)
        {
            event_t.status = OS_EVENT_SIGNAL;
        }
        else
        {
            event_t.status = OS_EVENT_TIMEOUT;
        }
    }

    /* Return flags before clearing */
    return (event_t);
}

/**
 * @brief  得到每个任务堆栈空间
 * @note   任务名      状态  ID    优先级  堆栈    CPU使用率
 *         任务状态:   r-运行  R-就绪  B-阻塞  S-挂起  D-删除
 * @retval None
 */
void get_task_info(void)
{
#if configUSE_TRACE_FACILITY
    uint32_t ulTotalRunTime;
    uint8_t uxArraySize = 0;
    /* 获取任务总数目 */
    uxArraySize = uxTaskGetNumberOfTasks();
    if (uxArraySize > configThread_Quantity)
    {
        return;
    }
    TaskStatus_t pxTaskStatusArray[configThread_Quantity] = {0};
    /* 获取每个任务的状态信息 */
    uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &ulTotalRunTime);
    for (uint8_t i = 0; i < uxArraySize; i++)
    {
        if (pxTaskStatusArray[i].xTaskNumber < configThread_Quantity)
        {
            os_task_stack[pxTaskStatusArray[i].xTaskNumber].pcTaskName = pxTaskStatusArray[i].pcTaskName;
            os_task_stack[pxTaskStatusArray[i].xTaskNumber].usStackHighWaterMark = pxTaskStatusArray[i].usStackHighWaterMark;
        }
    }
#endif
}
